package com.smart.common.config.knife4j;


import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.smart.common.entities.core.BaseEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.ModelPropertyBuilder;
import springfox.documentation.schema.Annotations;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * swagger3 枚举字段说明
 *
 * @author 夏绪秋
 * @date 2022-09-22
 */
@Slf4j
@Component
public class Swagger3Config implements ModelPropertyBuilderPlugin {


    @Override
    public void apply(ModelPropertyContext context) {

        // 获取当前字段的类型
        Optional<BeanPropertyDefinition> beanPropertyDefinition = context.getBeanPropertyDefinition();
        if (beanPropertyDefinition.isEmpty()) {
            return;
        }
        Class<?> fieldType = beanPropertyDefinition.get().getField().getRawType();

        descForEnumFields(context, fieldType);


    }

    /**
     * 返回是否应根据给定的分隔符调用插件
     */
    @Override
    public boolean supports(@NotNull DocumentationType documentationType) {
        return true;
    }


    /**
     * 为枚举字段设置注释
     */
    private void descForEnumFields(ModelPropertyContext context, Class<?> rawPrimaryType) {

        if (!rawPrimaryType.isEnum()) {
            return;
        }

        Optional<ApiModelProperty> annotation = Optional.empty();


        // 找到 @ApiModelProperty 注解修饰的枚举类
        if (context.getBeanPropertyDefinition().isPresent()) {
            annotation = Annotations.findPropertyAnnotation(context.getBeanPropertyDefinition().get(), ApiModelProperty.class);
        }


        //没有@ApiModelProperty 或者 notes 属性没有值，直接返回
        if (annotation.isEmpty()) {
            return;
        }


        Object[] subItemRecords;
        // 判断 rawPrimaryType 是否为枚举，且实现了 BaseEnum 接口
        if (rawPrimaryType.isEnum() && BaseEnum.class.isAssignableFrom(rawPrimaryType)) {
            // 拿到枚举的所有的值
            subItemRecords = rawPrimaryType.getEnumConstants();
        } else {
            return;
        }


        final List<String> displayValues = Arrays.stream(subItemRecords).filter(Objects::nonNull).map(item -> {
            BaseEnum mx = (BaseEnum) item;
            return String.valueOf(mx.name()).concat("=").concat(mx.getLabel());
        }).collect(Collectors.toList());


        String joinText = " (" + String.join("; ", displayValues) + ")";
        try {
            // 拿到字段上原先的描述
            Field mField = ModelPropertyBuilder.class.getDeclaredField("description");
            mField.setAccessible(true);
            joinText = "枚举属性:" + joinText;
        } catch (NoSuchFieldException noSuchFieldException) {
            //忽略错误
        }


        final ResolvedType resolvedType = context.getResolver().resolve(rawPrimaryType);
        context.getBuilder().description("<small style='color:red' >" + joinText + "</small>").type(resolvedType);

    }


}
